package cn.com.easy.pay.weixinpay.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.com.easy.dto.MessageDTO;
import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.weixinpay.config.WeixinPayConfig;
import cn.com.easy.utils.ResponseOutputUtils;

import com.tencent.business.RefundBusiness;
import com.tencent.business.RefundBusiness.ResultListener;
import com.tencent.common.Configure;
import com.tencent.protocol.refund_protocol.RefundReqData;
import com.tencent.protocol.refund_protocol.RefundResData;

/**
 * 微信退款基础控制器
 * 
 * @author nibili 2017年5月12日
 * 
 */
public abstract class WeixinPayRefundBaseController {

	private Logger logger = LoggerFactory.getLogger(WeixinPayRefundBaseController.class);

	/** 刷卡支付sdk,退款服务 */
	private RefundBusiness refundBusiness;

	/**
	 * 获取微信支付配置<br/>
	 * 
	 * @param httpRequest
	 * @return
	 * @throws BusinessException
	 * @author nibili 2017年5月12日
	 */
	public abstract WeixinPayConfig getWeixinPayConfig(HttpServletRequest httpRequest) throws BusinessException;

	/**
	 * 获取退款参数
	 * 
	 * @param httpRequest
	 * @return
	 * @throws BusinessException
	 * @author nibili 2017年5月12日
	 */
	public abstract RefundReqData getRefundReqData(Configure configure, HttpServletRequest httpRequest) throws BusinessException;

	/**
	 * 
	 * @param request
	 * @param response
	 * @param authCode
	 * @author nibili 2017年5月12日
	 */
	@RequestMapping("/refund")
	public void refund(final HttpServletRequest request, final HttpServletResponse response, String authCode) {
		try {

			WeixinPayConfig weixinPayConfig = getWeixinPayConfig(request);
			Configure configure = new Configure();
			configure.setKey(weixinPayConfig.getAppkey());
			configure.setAppID(weixinPayConfig.getAppid());
			configure.setMchID(weixinPayConfig.getMch_id());
			configure.setSubMchID(weixinPayConfig.getSubMchID());
			configure.setCertLocalPath(weixinPayConfig.getCertLocalPath());
			configure.setCertPassword(weixinPayConfig.getCertPassword());
			refundBusiness = new RefundBusiness(configure);

			//
			RefundReqData refundReqData = getRefundReqData(configure, request);
			//
			refundBusiness.run(refundReqData, new ResultListener() {

				@Override
				public void onFailByReturnCodeError(RefundResData refundResData) {
					WeixinPayRefundBaseController.this.onFailByReturnCodeError(request, response, refundResData);
				}

				@Override
				public void onFailByReturnCodeFail(RefundResData refundResData) {
					WeixinPayRefundBaseController.this.onFailByReturnCodeFail(request, response, refundResData);
				}

				@Override
				public void onFailBySignInvalid(RefundResData refundResData) {
					WeixinPayRefundBaseController.this.onFailBySignInvalid(request, response, refundResData);
				}

				@Override
				public void onRefundFail(RefundResData refundResData) {
					WeixinPayRefundBaseController.this.onRefundFail(request, response, refundResData);
				}

				@Override
				public void onRefundSuccess(RefundResData refundResData) {
					WeixinPayRefundBaseController.this.onRefundSuccess(request, response, refundResData);
				}

			});
		} catch (BusinessException ex) {
			logger.error("微信退款发生异常(自定义异常):" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		} catch (Exception ex) {
			logger.error("微信退款发生异常:" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		}

	}

	/**
	 * API返回ReturnCode不合法，支付请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问 <br/>
	 * 例：请检查每一个参数是否合法
	 * 
	 * @param refundResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeError(HttpServletRequest request, HttpServletResponse response, RefundResData refundResData);

	/**
	 * API返回ReturnCode为FAIL，支付API系统返回失败，请检测Post给API的数据是否规范合法 <br/>
	 * 例 ： 请检测Post给API的数据是否规范合法
	 * 
	 * @param request
	 * @param response
	 * @param scanPayResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeFail(HttpServletRequest request, HttpServletResponse response, RefundResData refundResData);

	/**
	 * 支付请求API返回的数据签名验证失败，有可能数据被篡改了<br/>
	 * 例：返回签名校验失败，此条数据疑似被篡改
	 * 
	 * @param request
	 * @param response
	 * @param scanPayResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailBySignInvalid(HttpServletRequest request, HttpServletResponse response, RefundResData refundResData);

	/**
	 * 退款失败<br/>
	 * 例：退款失败
	 * 
	 * @param request
	 * @param response
	 * @param refundResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onRefundFail(HttpServletRequest request, HttpServletResponse response, RefundResData refundResData);

	/**
	 * 退款成功
	 * 
	 * @param request
	 * @param response
	 * @param refundResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onRefundSuccess(HttpServletRequest request, HttpServletResponse response, RefundResData refundResData);
}
